//
//  AFFRichTextView.m
//  AnyfishApp
//
//  Created by Bob Lee on 14-4-18.
//  Copyright (c) 2014年 Anyfish. All rights reserved.
//




#import "AFFRichTextView.h"
#import <CoreText/CoreText.h>
#import "TYAttributedLabel.h"

@interface AFFRichTextView() <UIGestureRecognizerDelegate, TYAttributedLabelDelegate>  {
    CGRect drawFrame; // 绘制标准的范围，可实现控制绘制位置
    CGFloat deltaPlay;
    NSTimer *timerPlay;
    BOOL isMoveBack;
    BOOL canPlay; // 异步多次回来问题
    
    AFFRichTextBase *runSelected; ///< 当前操作的特殊类型
    TYAttributedLabel   *tLabel;    ///< 特殊控制view
    
    UITapGestureRecognizer *singleGesture;
    UILongPressGestureRecognizer *longPressGesture;
    UIColor *originalBgColor;
}

@end

@implementation AFFRichTextView

#pragma mark 初始化方法
- (id)initWithAFFDataText:(AFFDataText *)dataText
                   target:(id)target
                    frame:(CGRect)frame {
    self = [super init];
    if (self) {
        if(dataText==nil)
            dataText = [[AFFDataText alloc] init];
        
        _originalMsgText = dataText;
        deltaPlay = 0;
        self.delegage = target;
        self.rFrame = frame;
        self.numberOfline = -1;
        self.handleTap = YES;
        [self redrawViewWithAFFDataText:dataText first:YES];
        self.backgroundColor = [UIColor clearColor];
        self.userInteractionEnabled = NO;
    }
    
    return self;
}

- (void)setBackgroundColor:(UIColor *)backgroundColor {
    originalBgColor = backgroundColor;
    super.backgroundColor = backgroundColor;
}

- (void)setTempBgColor:(UIColor*)tempBgColor {
    UIColor *tt = originalBgColor;
    self.backgroundColor = tempBgColor;
    originalBgColor = tt;
}

#pragma mark 重绘更新内容

- (void)redrawViewWithAFFDataText:(AFFDataText *)dataText first:(BOOL)first {
    //    [self stopPlay];
    _originalMsgText = nil;
    
    if(dataText){
        if(dataText.isSpecialView){
            [self redrawSpecial:dataText];
        }else {
            
            if(!dataText.hadAnalyzed){
                if(CGRectEqualToRect(dataText.rFrame, CGRectZero)) {
                    dataText.rFrame = (CGRectEqualToRect(self.frame, CGRectZero)) ? self.rFrame:self.frame;
                }
                
                dataText.font = self.font?self.font:dataText.font;
                dataText.color = self.textColor?self.textColor:dataText.color;
                dataText.numberOfline = self.numberOfline>0?self.numberOfline:dataText.numberOfline;
                CGFloat widthSupport = dataText.numberOfline==1 ? self.widthSupport : dataText.widthSupport;
                [AFFRichTextView sizeOfAFFDataText:dataText widthSupport:MAX(widthSupport, 5)];
            }
            
            // 注意只有一行并且adjustFontToFitOneline；支持宽度过小不考虑
                        if(dataText.numberOfline==1 && self.adjustFontToFitOneline && dataText.numberOflineDrawed>1 && _widthSupport>50){
                            dataText.numberOfline = 2;
                            self.numberOfline = 2;

                            while (dataText.numberOflineDrawed>1) {
                                dataText.font = [UIFont fontWithSize_M:dataText.font.pointSize-0.5];
                                [AFFRichTextView sizeOfAFFDataText:dataText widthSupport:_widthSupport];

                                // 如果缩小到可以放下两排了就放2排
                                if(dataText.numberOflineDrawed==2 && dataText.heightUsed<(self.heightSupport>0?self.heightSupport:dataText.heightSupport)){
                                    dataText.numberOfline = 2;
                                    break;
                                }

                            }
                        }

            _attributeString = [[NSMutableAttributedString alloc] initWithAttributedString:dataText.attString];
        }
    }
    
    _originalMsgText = dataText;
    
    self.frame = self.rFrame;
    
    [self setNeedsDisplay];
    
    if(self.numberOfline==1&&self.isNeedMorelines){
        // 滚动问题后面调整
        //        canPlay = YES;
        //        [self setIsAutoPlay:YES];
    }
}

- (void)redrawViewWithAFFDataText:(AFFDataText *)dataText{
    [self redrawViewWithAFFDataText:dataText first:NO];
}

- (void)redrawSpecial:(AFFDataText *)dataText {
    // 组合一个
    for(UIView *sub in self.subviews){
        [sub removeFromSuperview];
    }
    
    if(CGRectEqualToRect(dataText.rFrame, CGRectZero)) {
        dataText.rFrame = (CGRectEqualToRect(self.frame, CGRectZero)) ? self.rFrame:self.frame;
    }
    
    dataText.font = self.font?self.font:dataText.font;
    dataText.color = self.textColor?self.textColor:dataText.color;
    dataText.numberOfline = self.numberOfline>0?self.numberOfline:dataText.numberOfline;
    CGFloat widthSupport = dataText.numberOfline==1 ? self.widthSupport : dataText.widthSupport;
    
    TYAttributedLabel *label = dataText.attLabel ? (TYAttributedLabel*)dataText.attLabel : [AFFRichTextView getAttLabel:dataText widthSupport:widthSupport];
    label.delegate = self;
    
    // 关联事件
    for(TYTextStorage *ty in label.textContainer.textStorages){
        if([ty isKindOfClass:[TYViewStorage class]]){
            TYViewStorage *tv = (TYViewStorage*)ty;
            if([tv.view isKindOfClass:[UIButton class]]){
                UIButton *btn = (UIButton*)tv.view;
                if(btn.allTargets.count==0){
                    [btn addTarget:self action:@selector(richBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
                }
            }
        }
    }
    
    self.frame = self.rFrame;
    [self addSubview:label];
    tLabel = label;
    
    [label sizeToFit];
    
    if([dataText needPullText]){
        [dataText pullDataWithConfig:nil block:^(BOOL result, id dataText) {
//            [UIHelper delayDoingWithAsyc:0.5 identify:nil block:^(NSObject *identifer) {
//                if(result && [self.originalMsgText isEqual:dataText] && self.superview){
//                    [_originalMsgText.mArrRichTextRuns removeAllObjects];
//                    _originalMsgText.hasCheckSpecial = NO;
//                    _originalMsgText.attLabel = nil;
//                    [self redrawViewWithAFFDataText:_originalMsgText];
//                }
//            }];
        }];
    }
}

+ (CTTextAlignment)getCTAlignment:(NSTextAlignment)alignment {
    switch (alignment) {
        case kTextAlignmentLeft:
            return kCTTextAlignmentLeft;
            
        case kTextAlignmentCenter:
            return kCTTextAlignmentCenter;
            
        case kTextAlignmentRight:
            return kCTTextAlignmentRight;
            
        default:
            break;
    }
    
    return kCTTextAlignmentLeft;
}

+ (TYAttributedLabel*)getAttLabel:(AFFDataText*)dataText widthSupport:(CGFloat)widthSupport {
    TYAttributedLabel *label = [[TYAttributedLabel alloc]initWithFrame:CGRectMake(0, 0, widthSupport, 0)];
    
    // lsb 2017-08-16 补充排版range，否则控件会比知道从哪里开始绘制
    NSMutableString *stringCombind = [[NSMutableString alloc] init];
    NSMutableArray *mArrStorage = [NSMutableArray array];
    
    // 这里切分处理文本中的表情
    for(int i=0; i< dataText.array.count; i++){
        AFFDataPartion *partion = [dataText.array objectWithIndex:i];
        
        UIFont *font = partion.font?partion.font:dataText.font;
        UIColor *textColor = partion.color?partion.color:dataText.color;
        
        CGFloat padding = 1.5;
        
        if(partion.type == kPartionTypeC_View){
            TYViewStorage *viewStorage = [[TYViewStorage alloc] init];
            viewStorage.view = partion.view;
            viewStorage.tag = partion.view.tag;
            viewStorage.drawAlignment = TYDrawAlignmentCenter;
            viewStorage.margin = UIEdgeInsetsMake(0, padding, 0, padding);
            [mArrStorage addObject:viewStorage];
            
            NSString *key = [NSString stringWithFormat:@"[v_%ld]", i];
            viewStorage.range = NSMakeRange(stringCombind.length, key.length);
            [stringCombind appendString:key];
            
        }else if(partion.type == kPartionTypeC_Button){
            UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
            
            if(partion.corner!=0){
                button.layer.cornerRadius = partion.corner>0?partion.corner:button.height/2;
                button.layer.masksToBounds = YES;
            }
            
            if(partion.borderWidth>0){
                button.layer.borderWidth = partion.borderWidth;
                button.layer.borderColor = partion.colorBorder.CGColor;
            }
            
            if(partion.colorBg){
                button.layer.backgroundColor = partion.colorBg.CGColor;
            }
            
            if(partion.containTitle){
                [button setTitle:partion.containTitle forState:UIControlStateNormal];
            }
            
            button.titleLabel.font = [UIFont fontWithSize_M:font.pointSize-6];
            [button setTitleColor:textColor forState:UIControlStateNormal];
            
            if(partion.tag>0){
                button.tag = partion.tag;
            }
            
            // 按钮大小目前先按照字体处理
            CGSize size = [partion.containTitle sizeWithAttributes:@{NSFontAttributeName:font}];
            size.height = MAX(font.ascender,size.height);
            button.frame = CGRectMake(0, 0, size.width, size.height);
            
            TYViewStorage *viewStorage = [[TYViewStorage alloc] init];
            viewStorage.view = button;
            viewStorage.tag = partion.tag;
            viewStorage.drawAlignment = TYDrawAlignmentCenter;
            viewStorage.margin = UIEdgeInsetsMake(0, padding, 0, padding);
            [mArrStorage addObject:viewStorage];
            
            NSString *key = [NSString stringWithFormat:@"[btn_%ld]", i];
            viewStorage.range = NSMakeRange(stringCombind.length, key.length);
            [stringCombind appendString:key];
            
        }else if(partion.type == kPartionTypeC_Label){
            // 大小目前先按照字体处理
            CGSize size = [partion.containTitle sizeWithAttributes:@{NSFontAttributeName:font}];
            size.height = MIN(font.ascender,size.height);
            CGRect frame = CGRectMake(0, 0, size.width, size.height);
            
            UILabel *lab = [[UILabel alloc] initWithFrame:frame];
            lab.textColor = textColor;
            lab.font = [UIFont fontWithSize_M:font.pointSize-6];
            lab.textAlignment = kTextAlignmentCenter;
            lab.text = partion.containTitle;
            
            if(partion.colorBg){
                lab.layer.backgroundColor = partion.colorBg.CGColor;
            }
            
            if(partion.corner!=0){
                lab.layer.cornerRadius = partion.corner>0?partion.corner:lab.height/2;
                lab.layer.masksToBounds = YES;
            }
            
            if(partion.borderWidth>0){
                lab.layer.borderWidth = partion.borderWidth;
                lab.layer.borderColor = partion.colorBorder.CGColor;
            }
            
            TYViewStorage *viewStorage = [[TYViewStorage alloc] init];
            viewStorage.view = lab;
            viewStorage.tag = partion.tag;
            viewStorage.drawAlignment = TYDrawAlignmentCenter;
            viewStorage.margin = UIEdgeInsetsMake(0, padding, 0, padding);
            [mArrStorage addObject:viewStorage];
            
            NSString *key = [NSString stringWithFormat:@"[lab_%ld]", i];
            viewStorage.range = viewStorage.realRange = NSMakeRange(stringCombind.length, key.length);
            [stringCombind appendString:key];
        }else if(partion.type == kPartionTypeC_Image){
            TYImageStorage *imageStorage = [[TYImageStorage alloc]init];
            imageStorage.cacheImageOnMemory = YES;
            imageStorage.imageName = partion.imgName;
            
            // 默认中心居中
            if(CGSizeEqualToSize(partion.size, CGSizeZero)){
                imageStorage.size = CGSizeMake(label.font.pointSize, label.font.ascender);
            }else {
                imageStorage.size = CGSizeMake(partion.size.width, partion.size.height);
                imageStorage.drawAlignment = (TYDrawAlignment)partion.alignment;
            }
            
            NSString *key = [NSString stringWithFormat:@"[img_%ld]", i];
            imageStorage.range = NSMakeRange(stringCombind.length, key.length);
            [mArrStorage addObject:imageStorage];
            
            [stringCombind appendString:key];
        }else {
            if(dataText.parseExp) {
                // 解析单个partion中的文字和表情等
                NSMutableArray *array = nil;
                NSString *original = partion.textAnalyze;
                
                array = partion.mArrParse;
                if(array==nil){
                    array = [NSMutableArray array];
                    original = [AFFRichTextURL analyzeText:partion runsArray:&array];
                    
                    if(dataText.parseType & ERichTextType_Html) {
                        original = [AFFRichTextHtml analyzeText:original runsArray:&array];
                    }
                    
                    if(dataText.parseType & ERichTextType_Number) {
                        original = [AFFRichTextNumber analyzeText:original runsArray:&array];
                    }
                    
                    partion.mArrParse = array;
                }
                
                if(![NSString isNilOrEmpty:original] && array.count>0){
                    NSString *subAppend = original; // 富文本中需要组合到一起的，最后赋值给stringCombind
                    
                    // 图片位置替换后原始文本解析的range会变化，需要控制，其他特殊run不会变化长度
                    NSInteger lengthOffset = 0;
                    for(NSInteger parseIndex=0; parseIndex<array.count; parseIndex++){
                        AFFRichTextBase *runx = [array objectWithIndex:parseIndex];
                        
                        if([runx isKindOfClass:[AFFRichTextExpression class]]){
                            // 将表情绘制的位置替换为图片目标key
                            NSString *key = [NSString stringWithFormat:@"[img_%ld_%ld]", i, parseIndex];
                            
                            AFFRichTextExpression *run = (AFFRichTextExpression*)runx;
                            NSRange range = NSMakeRange(run.range.location+lengthOffset, run.range.length);
                            subAppend = [subAppend stringByReplacingCharactersInRange:range withString:key];
                            lengthOffset += key.length-run.range.length;
                            
                            // 添加图片
                            TYImageStorage *imageStorage = [[TYImageStorage alloc]init];
                            imageStorage.imageName = run.expFullName;
                            imageStorage.imageAlignment = TYImageAlignmentCenter;
                            imageStorage.drawAlignment = TYDrawAlignmentCenter;
                            imageStorage.size = CGSizeMake(font.pointSize*1.5, font.ascender*1.5);
                            
                            //                            imageStorage.margin = UIEdgeInsetsMake(0, padding, 0, padding);
                            imageStorage.margin = UIEdgeInsetsMake(0, -padding, 0, 0);
                            imageStorage.range = NSMakeRange(stringCombind.length+range.location, key.length);
                            
                            [mArrStorage addObject:imageStorage];
                            
                        }else if([runx isKindOfClass:[AFFRichTextHtml class]] ||
                                 [runx isKindOfClass:[AFFRichTextNumber class]]) {
                            TYLinkTextStorage *linkTextStorage = [[TYLinkTextStorage alloc]init];
                            linkTextStorage.text = runx.originalText;
                            linkTextStorage.font = font;
                            linkTextStorage.textColor = runx.textColor;
                            linkTextStorage.linkData = partion;
                            linkTextStorage.underLineStyle = kCTUnderlineStyleSingle;
                            linkTextStorage.range = NSMakeRange(stringCombind.length+runx.range.location+lengthOffset, runx.originalText.length);
                            [mArrStorage addObject:linkTextStorage];
                            
                        }else if([runx isKindOfClass:[AFFRichTextURL class]]) {
                            TYTextStorage *txtStorage = [[TYTextStorage alloc] init];
                            txtStorage.text = runx.originalText;
                            txtStorage.textColor = textColor;
                            txtStorage.font = font;
                            txtStorage.range = NSMakeRange(stringCombind.length+runx.range.location+lengthOffset, runx.originalText.length);
                            [mArrStorage addObject:txtStorage];
                        }else {
                            TYTextStorage *txtStorage = [[TYTextStorage alloc] init];
                            txtStorage.text = runx.originalText;
                            txtStorage.textColor = textColor;
                            txtStorage.font = font;
                            txtStorage.range = NSMakeRange(stringCombind.length+runx.range.location+lengthOffset, runx.originalText.length);
                            [mArrStorage addObject:txtStorage];
                        }
                    }
                    
                    [stringCombind appendString:subAppend];
                }else {
                    TYTextStorage *txtStorage = [[TYTextStorage alloc] init];
                    txtStorage.text = partion.textAnalyze;
                    txtStorage.textColor = textColor;
                    txtStorage.font = font;
                    [mArrStorage addObject:txtStorage];
                    
                    [stringCombind appendString:partion.textAnalyze];
                }
            }
        }
    }
    
    
    TYTextContainer *container = [[TYTextContainer alloc] init];
    container.characterSpacing = 0.5;
    container.text = stringCombind;
    [container addTextStorageArray:mArrStorage];
    label.textContainer = container;
    label.font = dataText.font;
    label.textColor = dataText.color;
    label.backgroundColor = [UIColor clearColor];
    label.textAlignment = NSTextAlignmentToCTTextAlignment(dataText.textAlignment);// [AFFRichTextView getCTAlignment:dataText.textAlignment];
    label.numberOfLines = dataText.numberOfline;
    
    CGSize sizeUsed = [label getSizeWithWidth:widthSupport];
    dataText.heightUsed = sizeUsed.height;
    dataText.widthUsed = sizeUsed.width;
    
    dataText.attLabel = label;
    
    dataText.hasCheckSpecial = YES;
    return label;
}

+ (CGFloat)getAttViewHeight:(UIFont*)font {
    CGSize size = [@"测试" sizeWithAttributes:@{NSFontAttributeName:font}];
    size.height = MAX(font.ascender,size.height);
    
    return size.height;
}

- (void)stopPlay{
    if(timerPlay && timerPlay.isValid){
        [timerPlay invalidate];
        timerPlay = nil;
    }
    
    deltaPlay = 0;
    isMoveBack = NO;
}

- (void)startPlay {
    deltaPlay += isMoveBack ? 0.5 : -0.5;
    if((-deltaPlay + self.widthSupport >= self.widthUsed) || deltaPlay >=0){
        if(timerPlay && timerPlay.isValid){
            [timerPlay invalidate];
            timerPlay = nil;
        }
        
        isMoveBack = deltaPlay < 0;
        [self setIsAutoPlay:YES];
        
        return;
    }
    
    [self setNeedsDisplay];
}

- (void)setIsAutoPlay:(BOOL)isAutoPlay{
    // 判断是否需要循环播放(如果需要多行，且仅能绘制一行这时候一定超出可绘制最大宽度）
    if(self.numberOfline == 1 && isAutoPlay && self.isNeedMorelines){
        if(canPlay && timerPlay == nil){
            canPlay = NO;
//            [UIHelper delayDoingWithAsyc:_originalMsgText.deltaTime identify:nil block:^(NSObject *identifer) {
//                canPlay = YES;
//                timerPlay = [NSTimer scheduledTimerWithTimeInterval:0.1
//                                                             target:self
//                                                           selector:@selector(startPlay)
//                                                           userInfo:nil
//                                                            repeats:YES];
//                [[NSRunLoop currentRunLoop] addTimer:timerPlay forMode:NSRunLoopCommonModes];
//            }];
        }
    }
}

- (void)drawRect:(CGRect)rect{
    if(self.originalMsgText.isSpecialView){
        return;
    }
    
    for(UIView *sub in self.subviews){
        [sub removeFromSuperview];
    }
    
    CGFloat deltaX = 0, deltaY = 0, width = self.widthSupport, height = self.heightSupport;
    if(self.widthUsed<self.widthSupport){
        // 纠正绘制
        if(self.textAlignment == kTextAlignmentCenter){
            deltaX += (self.widthSupport-self.widthUsed)/2;
        }else if(self.textAlignment == kTextAlignmentRight){
            // 目前只能处理一行
            deltaX += self.widthSupport-self.widthUsed;
        }
        
        width = self.widthUsed;
    }
    
    if(self.heightUsed<self.heightSupport){
        deltaY = (self.heightSupport-self.heightUsed)/2;
        height = self.heightUsed;
    }
    
    // 处理绘制范围
    drawFrame = CGRectMake(deltaX, deltaY, MAX(width, 5), height);
    
    NSMutableAttributedString *attString = _attributeString;
    //设置颜色
    [attString addAttribute:(NSString *)kCTForegroundColorAttributeName value:(id)self.textColor.CGColor range:NSMakeRange(0,attString.length)];
    
    /*
     CTParagraphStyleSetting lineBreakMode;
     CTLineBreakMode lineBreak = kCTLineBreakByCharWrapping; //换行模式
     lineBreakMode.spec = kCTParagraphStyleSpecifierLineBreakMode;
     lineBreakMode.value = &lineBreak;
     lineBreakMode.valueSize = sizeof(CTLineBreakMode);
     //行间距
     CTTextAlignment alignment = kCTLeftTextAlignment;
     if(self.textAlignment == kTextAlignmentCenter) {
     alignment = kCTCenterTextAlignment;
     }
     
     if(self.textAlignment == kTextAlignmentRight) {
     alignment = kCTRightTextAlignment;
     }
     
     CTParagraphStyleSetting alignmentStyle;
     alignmentStyle.spec = kCTParagraphStyleSpecifierAlignment;
     alignmentStyle.valueSize = sizeof(alignment);
     alignmentStyle.value = &alignment;
     
     CTParagraphStyleSetting settings[] = {alignmentStyle};
     CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, 1);   //第二个参数为settings的长度
     [attString addAttribute:(NSString *)kCTParagraphStyleAttributeName
     value:(id)paragraphStyle
     range:NSMakeRange(0, attString.length)];*/
    
    if(attString.length>50){
        int i=0;
        i++;
    }
    
    if(_originalMsgText.mArrRichTextRuns.count>0){
        if(_originalMsgText.hideSpecial){
            [_originalMsgText.mArrRichTextRuns makeObjectsPerformSelector:@selector(setTextColor:) withObject:self.textColor];
        }else{
            // 没有设置字体、没有设置颜色的 统一设置
            NSMutableArray *emptyColor = [NSMutableArray array];
            for(AFFRichTextBase *run in _originalMsgText.mArrRichTextRuns){
                if(!run.textColor){
                    [emptyColor addObject:run];
                }
                
                // 特殊文本都有默认颜色，这里判断用户是否有重设置
                if([run isKindOfClass:[AFFRichTextHtml class]]){
                    run.textColor = self.htmlColor ? self.htmlColor : run.textColor;
                }
                
                if([run isKindOfClass:[AFFRichTextNumber class]]){
                    run.textColor = self.numberColor ? self.numberColor : run.textColor;
                }
                
                // 判断code 避免影响普通文本
                if([run isKindOfClass:[AFFRichTextURL class]] && run.code>0 && _urlColor){
                    run.textColor = _urlColor;
                }
            }
            
            // 进行批量设置属性值
            if(emptyColor.count>0){
                [emptyColor makeObjectsPerformSelector:@selector(setTextColor:) withObject:self.textColor];
            }
        }
        
        if(!singleGesture && _handleTap){
            // 注册单击，需要通过手势委托判断是否响应
            singleGesture = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                    action:@selector(handleSingleTap:)];
            singleGesture.numberOfTapsRequired = 1;
            singleGesture.delegate = self;
            [self addGestureRecognizer:singleGesture];
        }
        
        //设置特殊字体颜色
        for (AFFRichTextBase *textRun in _originalMsgText.mArrRichTextRuns)
        {
            [textRun replaceTextWithAttributedString:attString];
        }
        
        [_originalMsgText.mArrRichTextRuns makeObjectsPerformSelector:@selector(setIsDrawAsyc:) withObject:[NSNumber numberWithBool:self.isDrawAsyc]];
    }
    
    
    
    if(_handleLongPress && longPressGesture == nil){
        longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
        [longPressGesture setMinimumPressDuration:0.4];
        longPressGesture.delegate = self;
        [self addGestureRecognizer:longPressGesture];
    }
    
    // 这里可以调整下，使文本垂直居中
    if(drawFrame.size.width<=0){
        drawFrame = self.bounds;
    }
    
    //绘图上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    //修正坐标系
    CGAffineTransform textTran = CGAffineTransformIdentity;
    textTran = CGAffineTransformMakeTranslation(drawFrame.origin.x + deltaPlay, drawFrame.origin.y + drawFrame.size.height);
    textTran = CGAffineTransformScale(textTran, 1.0, -1.0);
    CGContextConcatCTM(context, textTran);
    
    //绘制
    int lineCount = 0;
    CFRange lineRange = CFRangeMake(0,0);
    CTTypesetterRef typeSetter = CTTypesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attString);
    float drawLineX = 0;
    float drawLineY = drawFrame.origin.y + drawFrame.size.height - self.font.ascender;
    CGFloat lineSpace = _originalMsgText.lineSpace;
    
    
    float subViewY = drawLineY;
    BOOL drawFlag = YES;
    [_originalMsgText.mDicRichTextRunRect removeAllObjects];
    
    while(drawFlag)
    {
        CGFloat curLineWidth = 0;
        CFIndex testLineLength = CTTypesetterSuggestLineBreak(typeSetter,lineRange.location,drawFrame.size.width);
    check:  lineRange = CFRangeMake(lineRange.location,testLineLength);
        CTLineRef line = CTTypesetterCreateLine(typeSetter,lineRange);
        CFArrayRef runs = CTLineGetGlyphRuns(line);
        
        if(runs==nil || runs==NULL || CFArrayGetCount(runs)==0)
            break;
        
        //边界检查
        CTRunRef lastRun = CFArrayGetValueAtIndex(runs, CFArrayGetCount(runs) - 1);
        CGFloat lastRunAscent;
        CGFloat laseRunDescent;
        CGFloat lastRunWidth  = CTRunGetTypographicBounds(lastRun, CFRangeMake(0,0), &lastRunAscent, &laseRunDescent, NULL);
        
        CGFloat lastRunPointX = drawLineX + CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(lastRun).location, NULL);
        //        CGFloat lastRunPointX = drawLineX + ((lineRange.location<CTRunGetStringRange(lastRun).location && (lineRange.location+lineRange.length)>CTRunGetStringRange(lastRun).location) ?CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(lastRun).location, NULL):0);
        
        if ((lastRunWidth + lastRunPointX) > drawFrame.size.width)
        {
            testLineLength--;
            CFRelease(line);
            goto check;
        }
        
        //绘制普通行元素
        drawLineX = CTLineGetPenOffsetForFlush(line,0,drawFrame.size.width);
        CGContextSetTextPosition(context,drawLineX,drawLineY);
        CTLineDraw(line,context);
        
        //绘制替换过的特殊文本单元
        for (int i = 0; i < CFArrayGetCount(runs); i++)
        {
            CTRunRef run = CFArrayGetValueAtIndex(runs, i);
            NSDictionary* attributes = (__bridge NSDictionary*)CTRunGetAttributes(run);
            AFFRichTextBase *textRun = [attributes objectForKey:kAttributeName];
            
            CGFloat runAscent,runDescent;
            CGFloat runWidth  = CTRunGetTypographicBounds(run, CFRangeMake(0,0), &runAscent, &runDescent, NULL);
            CGFloat runHeight = runAscent + (-runDescent);
            
            CGFloat runPointX = drawLineX + CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL);
            //            CGFloat runPointX = drawLineX + ((lineRange.location<CTRunGetStringRange(run).location && (lineRange.location+lineRange.length)>CTRunGetStringRange(run).location) ?CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL):0);
            CGFloat runPointY = drawLineY - (-runDescent);
            
            if (textRun)
            {
                
                CGRect runRect = CGRectMake(runPointX, runPointY, runWidth, runHeight);
                
                //                CGFloat delta = 1.0;
                //                drawLineX += delta*4;
                ////                runRect.origin.x += delta*4;
                //                runRect.origin.y -= delta;
                //                runRect.size.width += delta*2;
                //                runRect.size.height += delta*2;
                
                // 这里如果要使用控件显示图片，需要调整y值，因为绘制时y值是从下往上计算的；如果后期图片可以点击还得考虑范围或控件响应
                CGRect imgFrame = runRect;
                imgFrame.origin.y = subViewY-runPointY-lineSpace;
                if(self.textAlignment != kTextAlignmentLeft){
                    imgFrame.origin.x += deltaX;
                }
                
                //                BOOL isDraw = [textRun drawRunWithRect:runRect];
                BOOL isDraw = [textRun drawRunWithView:self rect:imgFrame];
                
                if (textRun.isResponseTouch)
                {
                    if (isDraw)
                    {
                        [_originalMsgText.mDicRichTextRunRect setObject:textRun forKey:[NSValue valueWithCGRect:runRect]];
                    }
                    else
                    {
                        runRect = CTRunGetImageBounds(run, context, CFRangeMake(0, 0));
                        runRect.origin.x = runPointX;
                        [_originalMsgText.mDicRichTextRunRect setObject:textRun forKey:[NSValue valueWithCGRect:runRect]];
                    }
                    
                    // 如果需要高亮显示当前特殊文本
                    [textRun drawHLightBackground:runRect context:context];
                }
            }
            
            curLineWidth += runWidth;
        }
        
        CFRelease(line);
        
        if(lineRange.location + lineRange.length >= attString.length)
        {
            drawFlag = NO;
        }
        
        lineCount++;
        if(lineCount>=self.numberOfline&&self.numberOfline>0){
            // 能在超过一行的画3个点在后面就好了，计算本行最大宽度
            if(drawFlag){
                //                CGRect frame = CGRectMake(finalX+3, finalY+(self.font.ascender + (- self.font.descender) + kLineSpace), 30, 12);
                //                [@"..." drawInRect:frame withFont:_font];
            }
            break;
        }
        
        drawLineY -= self.font.ascender + (- self.font.descender) + lineSpace;
        lineRange.location += lineRange.length;
    }
    
    _numberOflineDrawed = lineCount;
    if(typeSetter)
        CFRelease(typeSetter);
    
    // 只绘制一行时，如果需要拉取，拉取回来直接重绘
    if(self.numberOfline==1 && _originalMsgText && _originalMsgText.needPullText && !self.isAutoPullRefuse){
        [_originalMsgText pullDataWithConfig:nil block:^(BOOL result,id dataText) {
            if(result && [self.originalMsgText isEqual:dataText] && self.superview){
                [self redrawViewWithAFFDataText:dataText];
            }
        }];
    }
}

#pragma mark getter, setter

- (UIView*)tLabView {
    return tLabel;
}

- (void)setRFrame:(CGRect)rFrame {
    _original = rFrame.origin;
    _widthSupport = fabs(rFrame.size.width);
    _heightSupport = fabs(rFrame.size.height);
}

- (CGRect)rFrame {
    return CGRectMake(self.original.x, self.original.y, self.widthSupport, self.heightSupport);
}

- (CGFloat)widthSupport {
    if(_widthSupport>0)
        return _widthSupport;
    
    return _originalMsgText.widthSupport;
}

- (CGFloat)widthUsed {
    return _originalMsgText.widthUsed;
}

- (CGFloat)heightSupport {
    if(_heightSupport>0)
        return _heightTarget>0?_heightTarget: _heightSupport; // target是用户手动设置，目前只有在cellone基类处理时用到
    
    return _originalMsgText.heightSupport;
}

- (CGFloat)heightTarget {
    if(_heightTarget>0)
        return _heightTarget;
    
    return self.font.lineHeightUsed;//*self.numberOfline;
}

- (CGPoint)original {
    if(_original.x>0||_original.y>0)
        return _original;
    
    if(_originalMsgText.original.x>0||_originalMsgText.original.y>0)
        return _originalMsgText.original;
    
    return self.frame.origin;
}

- (CGFloat)heightUsed {
    return _originalMsgText.heightUsed;
}

- (NSTextAlignment)textAlignment {
    if(_textAlignment>0)
        return _textAlignment;
    
    return _originalMsgText.textAlignment;
}

- (UIFont*)font {
    if(_font)
        return _font;
    
    return _originalMsgText.font;
}

- (UIColor*)textColor {
    if(_textColor)
        return _textColor;
    
    return _originalMsgText.color;
}

- (NSInteger)numberOfline {
    if(_numberOfline>=0)
        return _numberOfline;
    
    return _originalMsgText.numberOfline;
}

- (NSInteger)numberOflineDrawed {
    return _originalMsgText.numberOflineDrawed;
}

- (BOOL)isNeedMorelines {
    return _originalMsgText.isNeedMorelines;
}

- (void)setHandleTap:(BOOL)handleTap {
    _handleTap = handleTap;
    
    if(!handleTap && singleGesture){
        [self removeGestureRecognizer:singleGesture];
    }
}

- (void)setHandleLongPress:(BOOL)handleLongPress {
    _handleLongPress = handleLongPress;
    
    if(!handleLongPress && longPressGesture){
        [self removeGestureRecognizer:longPressGesture];
    }
}

#pragma mark 计算文本绘制范围
+ (void)sizeOfAFFDataText:(AFFDataText *)dataText
             widthSupport:(CGFloat)widthSupport
{
    [dataText checkDataPulled];
    
    if(dataText.isSpecialView){
        [self getAttLabel:dataText widthSupport:widthSupport];
        return;
    }
    
    [dataText.mArrRichTextRuns removeAllObjects];
    
    AFFDataText  *temp = [AFFDataText initWithDataText:dataText];
    // 解析文本，判断需要多少高度
    NSMutableArray *array = dataText.mArrRichTextRuns;
    if(dataText.parseExp) {
        [AFFRichTextURL analyzeTextObjEx:temp runsArray:&array];
    }
    
    NSString *text = [temp showText];
    NSString *textAnalyzed = text?text:@"";
    
    if(dataText.parseType & ERichTextType_Html) {
        textAnalyzed = [AFFRichTextHtml analyzeText:textAnalyzed runsArray:&array];
    }
    
    if(dataText.parseType & ERichTextType_Number) {
        textAnalyzed = [AFFRichTextNumber analyzeText:textAnalyzed runsArray:&array];
    }
    
    dataText.textAnalyzed = textAnalyzed;
    
    // 没有设置字体、没有设置颜色的 统一设置
    
    if(dataText.hideSpecial){
        [array makeObjectsPerformSelector:@selector(setOriginalFont:) withObject:dataText.font];
    }else{
        
        NSMutableArray *arrFont = [NSMutableArray array];
        for(AFFRichTextBase *run in array){
            if(!run.originalFont){
                [arrFont addObject:run];
            }
        }
        
        // 进行批量设置属性值
        if(arrFont.count>0){
            [arrFont makeObjectsPerformSelector:@selector(setOriginalFont:) withObject:dataText.font];
        }
    }
    
    //要绘制的文本
    NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:textAnalyzed];
    
    //设置字体
    [attString addAttribute:(NSString*)kCTFontAttributeName value:(id)dataText.font range:NSMakeRange(0,attString.length)];
    
    if(attString.length>50){
        int i=0;
        i++;
    }
    
    //设置特殊字体颜色
    for (AFFRichTextBase *textRun in dataText.mArrRichTextRuns)
    {
        [textRun replaceTextWithAttributedString:attString];
    }
    
    //    if(attString.length>0){
    //        if(dataText.mArrRichTextRuns.count>0){
    //            for(AFFRichTextBase *rich in dataText.mArrRichTextRuns){
    //                if([rich isMemberOfClass:[AFFRichTextExpression class]]){
    //                    // 处理字间距
    //                    long number = 3.0;
    //                    CFNumberRef num = CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&number);
    //                    [attString addAttribute:(id)kCTKernAttributeName value:(__bridge id)num range:rich.range];
    //                    CFRelease(num);
    //                }
    //            }
    //        }
    //    }
    
    dataText.attString = attString;
    
    //绘制
    int lineCount = 0;
    CFRange lineRange = CFRangeMake(0,0);
    CTTypesetterRef typeSetter = CTTypesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attString);
    float drawLineX = 0;
    float drawLineY = 0;
    CGFloat lineSpace = dataText.lineSpace;
    BOOL drawFlag = YES;
    
    CGFloat maxWidth=0; //最大行宽度
    
    while(drawFlag)
    {
        CGFloat curLineWidth = 0;
        
        CFIndex testLineLength = CTTypesetterSuggestLineBreak(typeSetter,lineRange.location,widthSupport);
        if(testLineLength<0){
            break;
        }
        
    check:  lineRange = CFRangeMake(lineRange.location,testLineLength);
        CTLineRef line = CTTypesetterCreateLine(typeSetter,lineRange);
        CFArrayRef runs = CTLineGetGlyphRuns(line);
        
        if(runs==nil || runs==NULL || CFArrayGetCount(runs)==0)
            break;
        
        //边界检查
        CTRunRef lastRun = CFArrayGetValueAtIndex(runs, CFArrayGetCount(runs) - 1);
        CGFloat lastRunAscent;
        CGFloat laseRunDescent;
        CGFloat lastRunWidth  = CTRunGetTypographicBounds(lastRun, CFRangeMake(0,0), &lastRunAscent, &laseRunDescent, NULL);
        
        CFRange range = CTRunGetStringRange(lastRun);
        CFIndex index = range.location;
        
        if(range.location < lineRange.location){
            testLineLength--;
            CFRelease(line);
            goto check;
        }
        
        CGFloat lastRunPointX = drawLineX + CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(lastRun).location, NULL);
        //        CGFloat lastRunPointX = drawLineX +((lineRange.location<CTRunGetStringRange(lastRun).location && (lineRange.location+lineRange.length)>CTRunGetStringRange(lastRun).location) ?CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(lastRun).location, NULL):0);
        
        if ((lastRunWidth + lastRunPointX) > widthSupport)
        {
            testLineLength--;
            CFRelease(line);
            goto check;
        }
        
        //记录X偏移值
        drawLineX = CTLineGetPenOffsetForFlush(line,0,widthSupport);
        
        //绘制替换过的特殊文本单元
        for (int i = 0; i < CFArrayGetCount(runs); i++)
        {
            // 计算每个run的宽度，得到这一行最大宽度
            
            CTRunRef run = CFArrayGetValueAtIndex(runs, i);
            CGFloat runAscent,runDescent;
            CGFloat runWidth  = CTRunGetTypographicBounds(run, CFRangeMake(0,0), &runAscent, &runDescent, NULL);
            
            curLineWidth += runWidth;
        }
        
        CFRelease(line);
        
        
        if(lineRange.location + lineRange.length >= attString.length)
        {
            drawFlag = NO;
        }
        
        maxWidth = maxWidth>curLineWidth?maxWidth:curLineWidth;
        lineCount++;
        if(lineCount>dataText.numberOfline&&dataText.numberOfline>0){
            //            lineCount++;
            break;
        }
        
        drawLineY -= dataText.font.ascender + (-dataText.font.descender) + lineSpace;
        lineRange.location += lineRange.length;
    }
    
    CFRelease(typeSetter);
    temp = nil;
    attString = nil;
    array = nil;
    text = nil;
    textAnalyzed = nil;
    
    dataText.widthUsed = maxWidth+0.002;
    dataText.heightUsed = -drawLineY-lineSpace+2;
    dataText.numberOflineDrawed = lineCount;
    dataText.heightSupport = dataText.heightSupport<=0 ? dataText.heightUsed:dataText.heightSupport;
}

+ (CGSize)sizeOfText:(NSString*)text font:(UIFont*)font widthSuport:(CGFloat)widthSupport {
    AFFDataText *dataText = [[AFFDataText alloc] initWithText:text];
    dataText.numberOfline = 0;
    dataText.font = font;
    [self sizeOfAFFDataText:dataText widthSupport:widthSupport];
    return CGSizeMake(dataText.widthUsed, dataText.heightUsed);
}

#pragma mark - 事件处理

// addbutton方式添加的按钮
- (void)richBtnClicked:(UIButton*)btn {
    if([self.delegage respondsToSelector:@selector(richTextView:btnTag:)]){
        [self.delegage richTextView:self btnTag:btn.tag];
    }
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if(_originalMsgText.mArrRichTextRuns){
        UITouch *touch = [touches anyObject];
        CGPoint point = [touch locationInView:self];
        
        // CoreText context coordinates are the opposite to UIKit so we flip the bounds
        CGAffineTransform transform =  CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f);
        [_originalMsgText.mDicRichTextRunRect enumerateKeysAndObjectsUsingBlock:^(NSValue *keyRectValue, AFFRichTextBase *obj, BOOL *stop) {
            CGRect imgRect = [keyRectValue CGRectValue];
            CGRect rect = CGRectApplyAffineTransform(imgRect, transform);
            
            // point 是否在rect里
            if(CGRectContainsPoint(rect, point)){
                [self beginHighLightRun:obj];
                return ;
            }
        }];
    }
    
    if(_responseHit) {
        [self setTempBgColor:kRichColor_HLight];
    }

    
    [[self nextResponder] touchesBegan:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [self resignFirstResponder];
    
    if(_originalMsgText.mDicRichTextRunRect){
        UITouch *touch = [touches anyObject];
        CGPoint point = [touch locationInView:self];
        
        // CoreText context coordinates are the opposite to UIKit so we flip the bounds
        CGAffineTransform transform =  CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f);
        [_originalMsgText.mDicRichTextRunRect enumerateKeysAndObjectsUsingBlock:^(NSValue *keyRectValue, AFFRichTextBase *obj, BOOL *stop) {
            CGRect imgRect = [keyRectValue CGRectValue];
            CGRect rect = CGRectApplyAffineTransform(imgRect, transform);
            
            // point 是否在rect里
            if(CGRectContainsPoint(rect, point)){
                [self actionStart:obj];
                return ;
            }
        }];
    }
    
    // 这里需要处理点赞
    //        if(self.circleType == ECircleSubAction_Assit ||
    //           self.circleType == ECircleSubAction_Touch ||
    //           self.circleType == ECircleSubAction_Work ||
    //           self.circleType == ECircleSubComment){
    //            if([self.delegage respondsToSelector:@selector(richTextView:replyTo:)]){
    //                [self actionStart:nil];
    //                return;
    //            }
    //        }
    
    [[self nextResponder] touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesCancelled:touches withEvent:event];
    
    if(![self isFirstResponder]) // 自己已经接受了焦点就不能取消了
        [self resignFirstResponder];
}

- (void)beginHighLightRun:(AFFRichTextBase*)run{
    runSelected = run;
    run.isHLight = YES;
    [self setNeedsDisplay];
}

- (void)actionStart:(AFFRichTextBase*)run {
    [self resignFirstResponder];
    
    __weak AFFRichTextView *weakSelf = self;
    if(run){
        if([self.delegage respondsToSelector:@selector(richTextView:touchEndRun:)]){
            [self.delegage richTextView:weakSelf touchEndRun:run];
            return;
        }
    }
    
    // 其他特殊操作
//    if(self.circleType == ECircleSubComment){
//        if([self.delegage respondsToSelector:@selector(richTextView:replyTo:)]){
//            [self.delegage richTextView:weakSelf replyTo:self.replyTo];
//            return;
//        }
//    }
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}

- (BOOL)becomeFirstResponder {
    return [super becomeFirstResponder];
}

- (BOOL)resignFirstResponder {
    if([self isFirstResponder]){
        UIMenuController *menu = [UIMenuController sharedMenuController];
        [menu setMenuVisible:NO animated:YES];
        [menu update];
    }
    
    [UIView animateWithDuration:0.2
                          delay:0
                        options:UIViewAnimationOptionCurveEaseIn
                     animations:^{
                         self.backgroundColor = originalBgColor;
                     } completion:nil];
    
    if(runSelected && runSelected.isHLight){
        runSelected.isHLight = NO;
        runSelected = nil;
        [self setNeedsDisplay];
    }
    
    return [super resignFirstResponder];
}

- (void)copyInfo{
    if(self.delegage && [self.delegage respondsToSelector:@selector(richTextViewLongPressCopy:)]){
        [self.delegage richTextViewLongPressCopy:self];
    }else {
        if(![NSString isNilOrEmpty:[_originalMsgText showText]]){
            [[UIPasteboard generalPasteboard] setString:[_originalMsgText showText]];
            [self resignFirstResponder];
        }
    }
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if (self.hideCollect) {
        if (action == @selector(copyInfo))
        {
            return YES;
        }
    }
    else
    {
        if (action == @selector(copyInfo) || action == @selector(collectItem))
        {
            return YES;
        }
    }
    return NO;
}

#pragma mark - Gestures
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint point = [touch locationInView:self];
    
    // CoreText context coordinates are the opposite to UIKit so we flip the bounds
    CGAffineTransform transform =  CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f);
    
    __block BOOL find = NO;
    // 遍历run位置字典
    [_originalMsgText.mDicRichTextRunRect enumerateKeysAndObjectsUsingBlock:^(NSValue *keyRectValue, AFFRichTextBase *obj, BOOL *stop) {
        
        CGRect imgRect = [keyRectValue CGRectValue];
        CGRect rect = CGRectApplyAffineTransform(imgRect, transform);
        
        // point 是否在rect里
        if(CGRectContainsPoint(rect, point)){
            find = YES;
            *stop = YES;
            [self beginHighLightRun:obj];
        }
    }];
    
    //    if(!find && (self.actionType == _Mesace_Action_Comment || self.actionType==_Mesace_Action_Answer)){
    //        find = YES;
    //        [self setTempBgColor:kRichColor_HLight];
    //    }
    
    if(self.handleLongPress)
        find = YES;
    
    return find;
}

- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer {
    CGPoint point = [recognizer locationInView:self];
    
    // CoreText context coordinates are the opposite to UIKit so we flip the bounds
    CGAffineTransform transform =  CGAffineTransformScale(CGAffineTransformMakeTranslation(0, self.bounds.size.height), 1.f, -1.f);
    
    __block BOOL find = NO;
    
    // 遍历run位置字典
    [_originalMsgText.mDicRichTextRunRect enumerateKeysAndObjectsUsingBlock:^(NSValue *keyRectValue, AFFRichTextBase *obj, BOOL *stop) {
        
        CGRect imgRect = [keyRectValue CGRectValue];
        CGRect rect = CGRectApplyAffineTransform(imgRect, transform);
        
        if(CGRectContainsPoint(rect, point)){
            find = YES;
            *stop = YES;
            [self actionStart:obj];
        }
    }];
    
//    if(!find && (self.circleType == ECircleSubComment)){
//        [self actionStart:nil];
//        find = YES;
//    }
}

- (void)handleLongPress:(UILongPressGestureRecognizer *)longPress {
    if(longPress.state != UIGestureRecognizerStateBegan
       || ![self becomeFirstResponder])
        return;
    
    NSArray *arrItem = @[[[UIMenuItem alloc] initWithTitle:@"1" action:@selector(copyInfo)]];
    if(self.delegage && [self.delegage respondsToSelector:@selector(richTextViewLongPressItems)]){
        arrItem = [self.delegage richTextViewLongPressItems];
    }
    
    if(arrItem.count==0)
        return;
    
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu setMenuItems:arrItem];
    
    CGRect frame = self.frame;
    frame.origin = CGPointMake(0, 4);
    [menu setTargetRect:frame inView:self];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleMenuWillShowNotification:)
                                                 name:UIMenuControllerWillShowMenuNotification
                                               object:nil];
    [menu setMenuVisible:YES animated:YES];
    
    [menu update];
    
}

#pragma mark - Notification
- (void)handleMenuWillHideNotification:(NSNotification *)notification {
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIMenuControllerWillHideMenuNotification
                                                  object:nil];
    [self resignFirstResponder];
}

- (void)handleMenuWillShowNotification:(NSNotification *)notification {
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIMenuControllerWillShowMenuNotification
                                                  object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleMenuWillHideNotification:)
                                                 name:UIMenuControllerWillHideMenuNotification
                                               object:nil];
    [self setTempBgColor:kRichColor_HLight];
}

- (void)dealloc{
    [self dispose];
}

- (void)dispose {
    self.delegage = nil;
    
    if(timerPlay && timerPlay.isValid){
        [timerPlay invalidate];
        timerPlay = nil;
    }
    
    [self removeAllSubView];
    
    _font = nil;
    _textColor = nil;
    _htmlColor = nil;
    _numberColor = nil;
    _urlColor = nil;
    _delegage = nil;
    _originalMsgText = nil;
    _attributeString = nil;
    
    _delegage = nil;
    _htmlColor = nil;
    _numberColor = nil;
}

#pragma mark 特殊富文本绘制委托

- (void)attributedLabel:(TYAttributedLabel *)attributedLabel textStorageClicked:(id<TYTextStorageProtocol>)textStorage atPoint:(CGPoint)point {
    // 目前暂时只支持带code的文本点击
    if([textStorage isKindOfClass:[TYLinkTextStorage class]]){
        TYLinkTextStorage *link = (TYLinkTextStorage*)textStorage;
        if([self.delegage respondsToSelector:@selector(richTextView:link:)]){
            [self.delegage richTextView:self link:link.linkData];
        }
    }
}

- (void)attributedLabel:(TYAttributedLabel *)attributedLabel textStorageLongPressed:(id<TYTextStorageProtocol>)textStorage onState:(UIGestureRecognizerState)state atPoint:(CGPoint)point {
    
}

@end
